package com.fenqile.pop;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

import com.fenqile.pop.enums.AfterSaleKind;
import com.fenqile.pop.enums.AfterSaleStatus;
import com.fenqile.pop.enums.ExpressKind;
import com.fenqile.pop.enums.ExpressReceiptStatus;
import com.fenqile.pop.enums.ExpressStatus;
import com.fenqile.pop.enums.OrderStatus;
import com.fenqile.pop.trade.param.TradeExpressPushParameter.DeliveryInfo;
import com.fenqile.pop.utility.TypeSerializer;

public class ParameterTypeSerializer {
	
	public static final Map<Class<?>, TypeSerializer<?>> SERIALIZERS;
	static {
		final Map<Class<?>, TypeSerializer<?>> map = new HashMap<>();
		map.put(LocalDateTime.class, 		new LocalDateTimeSerializer());
		map.put(OrderStatus.class, 			new OrderStatusSerializer());
		map.put(AfterSaleKind.class, 		new OrderStatusSerializer());
		map.put(AfterSaleStatus.class, 		new OrderStatusSerializer());
		map.put(ExpressKind.class, 			new ExpressKindSerializer());
		map.put(ExpressStatus.class, 		new ExpressStatusSerializer());
		map.put(ExpressReceiptStatus.class, new ExpressReceiptStatusSerializer());
		map.put(DeliveryInfo.class, 		new DeliveryInfoSerializer());
		
		SERIALIZERS = Collections.unmodifiableMap(map);
	}
	
	
	@SuppressWarnings({ "rawtypes", "unchecked" })
	public String serialize(Object object) {
		Objects.requireNonNull(object, "cannot serialize null");
		TypeSerializer ts = SERIALIZERS.get(object.getClass());
		if (ts == null) return null;
		return ts.serialize(object);
	}
	
	public static class LocalDateTimeSerializer implements TypeSerializer<LocalDateTime> {
		public static final DateTimeFormatter DATETIMEFORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
		@Override
		public String serialize(LocalDateTime object) {
			return object.format(DATETIMEFORMATTER);
		}
	}
	
	public static class OrderStatusSerializer implements TypeSerializer<OrderStatus> {
		@Override
		public String serialize(OrderStatus obj) {
			return String.valueOf(obj.intValue());
		}
	}
	
	public static class AfterSaleKindSerializer implements TypeSerializer<AfterSaleKind> {
		@Override
		public String serialize(AfterSaleKind obj) {
			return String.valueOf(obj.intValue());
		}
	}
	
	public static class AfterSaleStatusSerializer implements TypeSerializer<AfterSaleStatus> {
		@Override
		public String serialize(AfterSaleStatus obj) {
			return String.valueOf(obj.intValue());
		}
	}
	
	public static class ExpressKindSerializer implements TypeSerializer<ExpressKind> {
		@Override
		public String serialize(ExpressKind obj) {
			return obj.name().toLowerCase();
		}
	}
	
	public static class ExpressStatusSerializer implements TypeSerializer<ExpressStatus> {
		@Override
		public String serialize(ExpressStatus obj) {
			return String.valueOf(obj.intValue());
		}
	}
	
	public static class ExpressReceiptStatusSerializer implements TypeSerializer<ExpressReceiptStatus> {
		@Override
		public String serialize(ExpressReceiptStatus obj) {
			return String.valueOf(obj.intValue());
		}
	}
	
	public static class DeliveryInfoSerializer implements TypeSerializer<DeliveryInfo> {
		private static char QUOTE = '\"';
		private static LocalDateTimeSerializer LDTS = new LocalDateTimeSerializer();
		
		@Override
		public String serialize(DeliveryInfo obj) {
			
			StringBuilder sb = new StringBuilder();
			sb.append('[');
			for (Map.Entry<LocalDateTime, String> o : obj) {
				sb
				.append('{')
					.append(QUOTE).append("time").append(QUOTE).append(':')
					.append(QUOTE).append(LDTS.serialize(o.getKey())).append(QUOTE).append(',')
					.append(QUOTE).append("context").append(QUOTE).append(':')
					.append(QUOTE).append(o.getValue()).append(QUOTE)
				.append('}')
				.append(',');
			}
			if (!obj.isEmpty()) sb.setLength(sb.length()-1);
			sb.append(']');
			
			return sb.toString();
		}
	}
	
	
}
